package com.tang.script.syntax;

import com.tang.script.command.AbstractScriptCommand;
import com.tang.script.command.ObjectCommand;
import com.tang.script.exceptions.ScriptException;
import com.tang.script.result.ScriptResult;
import com.tang.script.variable.Constant;
import com.tang.script.variable.Variable;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SyntaxChecker {
    private Class resultType;

    public void checkAndThrow(AbstractScriptCommand tAbstractScriptCommand,
                              Class resultType) {
        if (true) {
            return;
        }
        checkVariableName(tAbstractScriptCommand);
        ObjectCommand command = tAbstractScriptCommand.getScriptEngine()
                .getScriptCommandBuilder()
                .newObjectCommand()
                .scriptText(tAbstractScriptCommand.getScriptText())
                .variablesContainer(new FakeVariableContainer())
                .build();

        ScriptResult objectScriptResult = tAbstractScriptCommand
                .getScriptEngine()
                .executeScript(command);
        Object result = objectScriptResult.getResult();
        if (result instanceof Collection) {
            throw new ScriptException("不能将明细项直接运算");
        }
        if (!resultType.isAssignableFrom(result.getClass())) {
            throw new ScriptException("公式计算结果类型有误: 需要的类型:" + resultType + ", 实际返回类型: " + result.getClass());
        }
    }

    private void checkVariableName(AbstractScriptCommand tAbstractScriptCommand) {
        Map<String, Variable> variables = tAbstractScriptCommand.getVariables();
        Map<String, Constant> constants = tAbstractScriptCommand.getConstants();
        List<String> functions = tAbstractScriptCommand.getFunctions();
        Pattern pattern = Pattern.compile("^(\\w|\\d|\\.)+$");

        if (Objects.nonNull(variables)) {
            for (Variable variable : variables.values()) {
                String value = variable.getValue();
                simpleCheck(value);
                Matcher matcher = pattern.matcher(value);
                if (!matcher.find()) {
                    throw new ScriptException("无法识别的变量: " + value);
                }
            }

            for (Constant con : constants.values()) {
                String value = con.getValue();
                simpleCheck(value);
                Matcher matcher = pattern.matcher(value);
                if (!matcher.find()) {
                    throw new ScriptException("无法识别的变量: " + value);
                }
            }

            for (String fun : functions) {
                String value = fun;
                simpleCheck(value);
                Matcher matcher = pattern.matcher(value);
                if (!matcher.find()) {
                    throw new ScriptException("无法识别的变量: " + value);
                }
            }
        }
    }

    private void simpleCheck(String variableName) {
        String[] split = variableName.split("\\.");
        if (split.length > 2) throw new ScriptException("无法识别的变量: " + variableName);
    }
}
